package com.oswift.cms.dao;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.oswift.utils.exception.ErrorCode;
import com.oswift.utils.exception.PlatException;

public class BaseDao<T>
{
    /**
     * 日志实例
     */
    private static Logger log = LoggerFactory.getLogger(BaseDao.class);

    /**
     * mybatis配置文件中的新增头部
     */
    private static final String HEAD_ADD = "{0}.add";

    /**
     * mybatis配置文件中的删除头部
     */
    private static final String HEAD_DEL = "{0}.del";

    /**
     * mybatis配置文件中的修改头部
     */
    private static final String HEAD_UPDATE = "{0}.update";

    /**
     * mybatis配置文件中的查询一条记录头部
     */
    private static final String HEAD_SELECT_ONE = "{0}.one";

    /**
     * mybatis配置文件中的查询列表头部
     */
    private static final String HEAD_SELECT_LIST = "{0}.list";

    /**
     * mybatis配置文件中的查询查询数据库中某个表有多少列的头部
     */
    private static final String HEAD_SELECT_COUNT = "{0}.count";

    /**
     * 获取bean的类名，用于查找sql的值
     */
    private String className;

    /**
     * 映射生成SqlSession对象
     */
    @Autowired
    protected SqlSession sqlSession;

    /**
     *
     * 构造函数
     *
     * @param className
     *            bean类名称
     */
    public BaseDao(String className)
    {
        this.className = className;
    }

    /**
     *
     * 向数据库添加一条记录
     *
     * @author zhuou
     * @param type
     *            泛型类型
     * @return 影响行数
     */
    public int add(T type) throws PlatException
    {
        String sqlKey = replace(HEAD_ADD);

        try
        {
            return sqlSession.insert(sqlKey, type);
        }
        catch (Exception e)
        {
            log.error("Fail to add. sql=" + sqlKey, e);
            throw new PlatException(ErrorCode.COMMON_DB_ERROR);
        }
    }

    /**
     *
     * 删除数据库一条记录
     *
     * @author zhuou
     * @param params
     *            删除参数
     * @return 影响行数
     */
    public int delete(Object params) throws PlatException
    {
        int result = 0;
        String sqlKey = replace(HEAD_DEL);

        try
        {
            if (null == params)
            {
                result = sqlSession.delete(sqlKey);
            }
            else
            {
                result = sqlSession.delete(sqlKey, params);
            }
        }
        catch (Exception e)
        {
            log.error("Fail to delete. sql=" + sqlKey, e);
            throw new PlatException(ErrorCode.COMMON_DB_ERROR);
        }
        return result;
    }

    /**
     *
     * 修改数据库记录值
     *
     * @author zhuou
     * @param params
     *            修改参数
     * @return 影响行数
     */
    public int update(Object params) throws PlatException
    {
        int result = 0;
        String sqlKey = replace(HEAD_UPDATE);

        try
        {
            if (null == params)
            {
                result = sqlSession.update(sqlKey);
            }
            else
            {
                result = sqlSession.update(sqlKey, params);
            }
        }
        catch (Exception e)
        {
            log.error("Fail to update. sql=" + sqlKey, e);
            throw new PlatException(ErrorCode.COMMON_DB_ERROR);
        }
        return result;
    }

    /**
     *
     * 查询数据库中一条记录
     *
     * @author zhuou
     * @param params
     *            查找参数
     * @return 返回类型为T的一条记录
     */
    @SuppressWarnings("unchecked")
    public T selectOne(Object params) throws PlatException
    {
        T obj;
        String sqlKey = replace(HEAD_SELECT_ONE);

        try
        {
            if (null == params)
            {
                obj = (T)sqlSession.selectOne(sqlKey);
            }
            else
            {
                obj = (T)sqlSession.selectOne(sqlKey, params);
            }
        }
        catch (Exception e)
        {
            log.error("Fail to selectOne. sql=" + sqlKey, e);
            throw new PlatException(ErrorCode.COMMON_DB_ERROR);
        }
        return obj;
    }

    /**
     *
     * 查询数据库中多条记录
     *
     * @author zhuou
     * @param params
     * @return list列表
     */
    public List<T> selectList(Object params) throws PlatException
    {
        List<T> obj;
        String sqlKey = replace(HEAD_SELECT_LIST);

        try
        {
            if (null == params)
            {
                obj = sqlSession.selectList(sqlKey);
            }
            else
            {
                obj = sqlSession.selectList(sqlKey, params);
            }
        }
        catch (Exception e)
        {
            log.error("Fail to selectList. sql=" + sqlKey, e);
            throw new PlatException(ErrorCode.COMMON_DB_ERROR);
        }
        return obj;
    }

    /**
     *
     * 查询数据库中某个表有多少列，如果params=null,则没有查询条件
     *
     * @author zhuou
     * @param params
     *            查询条件
     * @return int类型，多少列
     */
    public int selectCount(Object params) throws PlatException
    {
        int result = 0;
        String sqlKey = replace(HEAD_SELECT_COUNT);

        try
        {
            if (null == params)
            {
                result = (Integer)sqlSession.selectOne(sqlKey);
            }
            else
            {
                result = (Integer)sqlSession.selectOne(sqlKey, params);
            }
        }
        catch (Exception e)
        {
            log.error("Fail to selectCount. sql=" + sqlKey, e);
            throw new PlatException(ErrorCode.COMMON_DB_ERROR);
        }
        return (result);
    }

    /**
     *
     * 拼接mybatis xml的id值
     *
     * @author zhuou
     * @param head
     *            头信息
     * @return String
     */
    private String replace(String head)
    {
        return head.replace("{0}", className);
    }

    /**
     *
     * 获取SqlSession类实例
     *
     * @author zhuou
     * @return SqlSession
     */
    public SqlSession getSqlSession()
    {
        return sqlSession;
    }

    /**
     *
     * 赋SqlSession类实例
     *
     * @author zhuou
     * @param sqlSession
     */
    public void setSqlSession(SqlSession sqlSession)
    {
        this.sqlSession = sqlSession;
    }
}
